// 导入axios库
import axios, { type AxiosInstance as AxiosInstanceType, type AxiosRequestConfig as AxiosRequestConfigType, type AxiosResponse as AxiosResponseType, type InternalAxiosRequestConfig as InternalAxiosRequestConfigType, type AxiosError as AxiosErrorType } from 'axios'

// 重新导出类型以便外部使用
export type AxiosRequestConfig = AxiosRequestConfigType
export type AxiosResponse<T = any> = AxiosResponseType<T>
export type InternalAxiosRequestConfig = InternalAxiosRequestConfigType
export type AxiosError = AxiosErrorType
import { ElMessage } from 'element-plus'

// 创建axios实例
const service: AxiosInstanceType = axios.create({
  // API基础URL，使用相对路径以便通过vite代理
  // 注意：不需要设置baseURL为'/api'，因为vite.config.ts中的代理配置已经处理了路径重写
  baseURL: '',
  // 请求超时时间
  timeout: 10000,
  // 请求头配置
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

// 请求拦截器
// let isRefreshing = false
// const refreshSubscribers: Array<(token: string) => void> = []

// 在文件顶部获取token，避免在拦截器中使用useAuthStore
const getToken = (): string | null => {
  return localStorage.getItem('token')
}

// 添加请求拦截器
const setupInterceptors = () => {
  service.interceptors.request.use(
    (config: AxiosRequestConfigType): InternalAxiosRequestConfigType => {
      // 在发送请求之前做些什么
      const token = getToken()
      
      // 如果存在token，添加到请求头
      if (token) {
        config.headers = {
          ...config.headers,
          'Authorization': `Bearer ${token}`
        } as AxiosRequestConfig['headers']
      }
      
      return config as InternalAxiosRequestConfig
    },
    (error: AxiosErrorType): Promise<AxiosErrorType> => {
      // 处理请求错误
      console.error('请求错误:', error)
      return Promise.reject(error)
    }
  )

  // 添加响应拦截器
  service.interceptors.response.use(
    (response: AxiosResponseType): AxiosResponseType => {
      // 对响应数据做点什么
      console.log('响应拦截器收到数据:', response.config.url)
      console.log('完整响应对象:', response)
      console.log('响应状态码:', response.status)
      console.log('响应数据:', response.data)
      
      const res = response.data
      const url = response.config.url || ''
      
      // 确保res不是undefined或null
      if (res === undefined || res === null) {
        console.error('响应数据为空:', response.config.url)
        response.data = { error: '响应数据为空' }
        return response
      }
      
      // 特殊处理登录接口响应，因为它返回的格式不同
      if (url.includes('/auth/token')) {
        console.log('处理登录接口响应:', url)
        console.log('登录响应数据:', res)
        console.log('登录响应数据包含的字段:', typeof res === 'object' ? Object.keys(res) : '不是对象')
        // 登录接口返回的是TokenResponse对象，确保返回完整响应
        return response
      }
      
      // 特殊处理获取用户信息接口
      if (url.includes('/auth/me')) {
        // 检查响应是否是HTML内容
        if (typeof res === 'string' && res.includes('<!doctype html>')) {
          // 不再打印error日志，而是直接抛出格式错误
          throw new Error('Invalid response format for user info')
        }
        
        return response
      }
      
      // 对于其他接口，检查code字段
      // 这里根据后端返回的状态码进行处理
      // 假设状态码为0表示成功
      if (res.code !== 0) {
        ElMessage.error(res.message || '请求失败')
        throw new Error(res.message || 'Error')
      }
      
      return response
    },
    async (error: AxiosErrorType): Promise<AxiosErrorType> => {
      // 处理响应错误
      const { response } = error
      
      // 处理token过期的情况
      if (response?.status === 401) {
        // 判断是否是刷新token的请求，如果不是，则跳转到登录页
        if (!response.config.url?.includes('/refresh-token')) {
          // 清除token
          localStorage.removeItem('token')
          // 跳转到登录页
          window.location.href = '/login'
        }
      } else if (response?.status === 403) {
        ElMessage.error('没有权限访问该资源')
      } else if (response && response.status >= 500) {
        ElMessage.error('服务器内部错误，请稍后重试')
      } else if (response?.status) {
        ElMessage.error(`请求失败：${response.status}`)
      } else if (!response) {
        ElMessage.error('网络错误，请检查网络连接')
      }
        
      return Promise.reject(error)
    }
  )
}

// 初始化拦截器
setupInterceptors()

// 请求方法封装
const request = {
  /**
   * GET请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 额外配置
   */
  get<T = any>(url: string, params?: any, config?: AxiosRequestConfigType): Promise<T> {
    return service.get<T>(url, { params, ...config }).then((response: AxiosResponseType<T>) => response.data)
  },

  /**
   * POST请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 额外配置
   */
  post<T = any>(url: string, data?: any, config?: AxiosRequestConfigType): Promise<T> {
    console.log('[POST] 1. 准备发送请求:', url)
    console.log('[POST] 1.1 请求数据:', data)
    console.log('[POST] 1.2 请求配置:', config)
    
    // 创建一个包装的Promise，以便更好地追踪执行流程
    return new Promise((resolve, reject) => {
      console.log('[POST] 2. 创建Promise并开始执行service.post')
      
      service.post<T>(url, data, config)
        .then((result: any) => {
          // 检查result是否为AxiosResponse对象
          if (result && result.config && result.data) {
            // 如果是完整响应对象，提取data部分
            console.log('[POST] 3. 收到响应对象，URL:', url)
            console.log('[POST] 3.1 完整响应对象:', result)
            console.log('[POST] 3.2 响应数据:', result.data)
            console.log('[POST] 3.3 响应数据类型:', typeof result.data)
            
            if (result.data === undefined) {
              console.error('[POST] 3.4 严重问题：response.data是undefined!')
              reject(new Error('Response data is undefined'))
            } else {
              console.log('[POST] 4. 返回响应数据')
              resolve(result.data)
            }
          } else {
            // 如果直接返回了数据（旧的拦截器行为），则直接返回
            console.log('[POST] 3. 收到直接数据响应，URL:', url)
            console.log('[POST] 3.1 响应数据:', result)
            console.log('[POST] 3.2 响应数据类型:', typeof result)
            
            if (result === undefined) {
              console.error('[POST] 3.3 严重问题：响应数据是undefined!')
              reject(new Error('Response data is undefined'))
            } else {
              console.log('[POST] 4. 返回响应数据')
              resolve(result)
            }
          }
        })
        .catch(error => {
          console.error('[POST] 5. 请求失败，URL:', url)
          console.error('[POST] 5.1 错误对象:', error)
          console.error('[POST] 5.2 错误详情:', JSON.stringify(error, null, 2))
          if (error.response) {
            console.error('[POST] 5.3 错误响应状态码:', error.response.status)
            console.error('[POST] 5.4 错误响应数据:', error.response.data)
          }
          reject(error)
        })
    })
  },

  /**
   * PUT请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 额外配置
   */
  put<T = any>(url: string, data?: any, config?: AxiosRequestConfigType): Promise<T> {
    return service.put<T>(url, data, config).then((response: AxiosResponseType<T>) => response.data)
  },

  /**
   * DELETE请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 额外配置
   */
  delete<T = any>(url: string, params?: any, config?: AxiosRequestConfigType): Promise<T> {
    return service.delete<T>(url, { params, ...config }).then((response: AxiosResponseType<T>) => response.data)
  },

  /**
   * PATCH请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 额外配置
   */
  patch<T = any>(url: string, data?: any, config?: AxiosRequestConfigType): Promise<T> {
    return service.patch<T>(url, data, config).then((response: AxiosResponseType<T>) => response.data)
  },

  /**
   * 上传文件
   * @param url 请求地址
   * @param file 文件对象
   * @param fileName 文件名
   * @param config 额外配置
   */
  upload<T = any>(
    url: string,
    file: File,
    fileName: string = 'file',
    config?: AxiosRequestConfigType
  ): Promise<T> {
    const formData = new FormData()
    formData.append(fileName, file)
    
    return service.post<T>(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    }).then((response: AxiosResponseType<T>) => response.data)
  },

  /**
   * 下载文件
   * @param url 请求地址
   * @param params 请求参数
   * @param filename 文件名
   */
  download(url: string, params?: any, filename?: string): void {
    service
      .get(url, {
        params,
        responseType: 'blob'
      })
      .then((response: AxiosResponseType<Blob>) => {
        const blob = new Blob([response.data])
        const url = window.URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = filename || 'download'
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        window.URL.revokeObjectURL(url)
      })
  }
}

export default request